package com.apes.fico.masterdata.gl.service;

import com.apes.fico.masterdata.gl.model.*;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.fico.masterdata.gl.respository.AccountingChartDistributionCompanyRepository;
import com.apes.fico.masterdata.gl.respository.AccountingChartRepository;
import com.apes.fico.masterdata.gl.respository.AccountingOperatingChartRepository;
import com.apes.fico.masterdata.gl.respository.AccountingSystemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @ClassName AccountingChartService
 * @Description TODO
 * @Author pengyb
 * @Date 2018/12/27 9:18
 * @Version 1.0
 **/
@Service("accountingChartService")
public class AccountingChartService extends DomainService {
    @Autowired
    private AccountingChartRepository accountingChartRepository;
    @Autowired
    private AccountingChartDistributionCompanyRepository accountingChartDistributionCompanyRepository;
    @Autowired
    private AccountingSystemRepository accountingSystemRepository;
    @Autowired
    private AccountingOperatingChartRepository accountingOperatingChartRepository;

    /**
     * 保存
     *
     * @param request
     * @return
     */
    public AccountingChart save(SimpleRequest request) {
        AccountingChart accountingChart = request.getO(AccountingChart.class);
        accountingChart.checkAcl();
        if (accountingChart.getParent() == null) {
            accountingChart.setId(accountingChart.getCode());
        } else {
            accountingChart.setId(accountingChart.getAccSystem().getId() + accountingChart.getCode());
        }
        accountingChart.setCreateDate(new Date());
        AccountingChart accchart = accountingChartRepository.saveAndFlush(accountingChart);
        sync(accchart);
        return accchart;
    }

    /**
     * 修改
     *
     * @param request
     * @return
     */
    public AccountingChart update(SimpleRequest request) {
        checkData(request);
        AccountingChart accountingChart = request.getO(AccountingChart.class);
        accountingChart.checkAcl();
        accountingChart.setUpdateDate(new Date());
        AccountingChart accChart = accountingChartRepository.saveAndFlush(accountingChart);
        try {
            syncUpdate(accChart);
        } catch (JpaSystemException exception){
            throw new RuntimeException("该辅助核算已被使用，无法删除");
        }
        return accChart;
    }

    /**
     * 删除
     *
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        checkData(request);
        AccountingChart accountingChart = request.getO(AccountingChart.class);
        accountingChartRepository.delete(accountingChart.getId());
        return "删除成功";
    }

    /**
     * 检查
     *
     * @param request
     */
    public void checkData(SimpleRequest request) {
        AccountingChart accountingChart = accountingChartRepository.findOne((String) request.get("id"));
        if (accountingChart == null) throw new RuntimeException("会计科目表科目(集团科目表)" + accountingChart.getId() + "不存在");
        if (accountingChart.getVersion() != (int) request.get("version"))
            throw new RuntimeException("会计科目表科目(集团科目表)" + accountingChart.getId() + "已更新或已删除");
    }

    /**
     * 检查级次,通过级次生成代码
     *
     * @param request
     * @return
     */
    public String checkClasses(SimpleRequest request) {

        List<AccountingChart> accountingCharts = accountingChartRepository.findAllByCodeAndAccSystemAndClasses((String) request.get("code"), (String) request.get("accSystem"), (double) ((int) request.get("classes") * 1.0));
        int max = 1;
        if (accountingCharts.size() != 0 || !accountingCharts.isEmpty()) {
            max = Integer.parseInt(accountingCharts.get(0).getCode());
            for (int i = 0; i < accountingCharts.size(); i++) {
                if (max < Integer.parseInt(accountingCharts.get(i).getCode())) {
                    max = Integer.parseInt(accountingCharts.get(i).getCode());
                }
            }
        } else {
            max = Integer.parseInt((String) request.get("code")) * 100;
        }
        return max + 1 + "";
    }


    /**
     * 同步写入运营科目表
     *
     * @param accountingChart
     * @return
     */
    public void sync(AccountingChart accountingChart) {
        List<AccountingChartDistributionCompany> accountingChartDistributionCompanies = accountingChartDistributionCompanyRepository.findAllByAccSystem_Id(accountingChart.getAccSystem().getId());
        if (!accountingChartDistributionCompanies.isEmpty()) {
            List<AccountingOperatingChart> accountingOperatingChartList = new ArrayList<>();
            accountingChartDistributionCompanies.stream().forEach(accChartDistributionCompany -> {
                AccountingOperatingChart accOpChart = new AccountingOperatingChart();
                accOpChart.setCode(accountingChart.getCode());
                accOpChart.setAccSystem(accountingChart.getAccSystem());
                accOpChart.setCompany(accChartDistributionCompany.getCompany());
                accOpChart.setName(accountingChart.getName());
                accOpChart.setDisplayName(accountingChart.getDisplayName());
                accOpChart.setBalanorient(accountingChart.getBalanorient());
                accOpChart.setValid(true);
                accOpChart.setInheritFlag(true);
                accOpChart.setFinalFlag(accountingChart.isFinalFlag());
                accOpChart.setClasses(accountingChart.getClasses());
                accOpChart.setAccGroup(accountingChart.getAccGroup());
                accOpChart.setId(accOpChart.getCompany().getId() + "." + accOpChart.getCode());
                if (accountingChart.getParent() != null) {
                    AccountingOperatingChart parent = new AccountingOperatingChart();
                    parent.setId(accOpChart.getCompany().getId() + "." + accountingChart.getParent().getCode());
                    accOpChart.setParent(parent);
                }
                if (accountingChart.getAccChartAuxiliaries() != null) {
                    List<AccountingOperatingChartAuxiliary> accAux = new ArrayList<>();
                    accountingChart.getAccChartAuxiliaries().stream().forEach(accAuxs -> {
                        AccountingOperatingChartAuxiliary accOpChartAuxiliary = new AccountingOperatingChartAuxiliary();
                        AccountingOperatingChart accountingOperatingChart = new AccountingOperatingChart();
                        accountingOperatingChart.setId(accOpChart.getCompany().getId() + "." + accAuxs.getAccChart().getCode());
                        accOpChartAuxiliary.setSequence(accAuxs.getSequence());
                        accOpChartAuxiliary.setAccAuxiliaryProject(accAuxs.getAccAuxiliaryProject());
                        accOpChartAuxiliary.setAccOperatingChart(accountingOperatingChart);
                        accAux.add(accOpChartAuxiliary);
                    });
                    accOpChart.setAccOperatingChartAuxiliaryList(accAux);
                }
                accountingOperatingChartList.add(accOpChart);
            });
            accountingOperatingChartRepository.save(accountingOperatingChartList);//保存转化后的运营科目表,此时运营科目表已有数据
        }
    }


    /**
     * 同步更新运营科目表
     *
     * @param accountingChart
     * @return
     */
    public void syncUpdate(AccountingChart accountingChart) {
        List<AccountingChartDistributionCompany> accountingChartDistributionCompanies = accountingChartDistributionCompanyRepository.findAllByAccSystem_Id(accountingChart.getAccSystem().getId());
        if (!accountingChartDistributionCompanies.isEmpty()) {
            accountingChartDistributionCompanies.forEach(accChartDistributionCompany -> {
                AccountingOperatingChart accOpChart = accountingOperatingChartRepository.findAllByAccChart(accountingChart.getCode(), accChartDistributionCompany.getCompany().getId());
                accOpChart.setName(accountingChart.getName());
                accOpChart.setDisplayName(accountingChart.getDisplayName());
                accOpChart.setBalanorient(accountingChart.getBalanorient());
                accOpChart.setValid(accountingChart.isValid());
                accOpChart.setFinalFlag(accountingChart.isFinalFlag());
                accOpChart.setClasses(accountingChart.getClasses());
                accOpChart.setAccGroup(accountingChart.getAccGroup());
                accOpChart.setPrice(accountingChart.isPrice());
                accOpChart.setQuantity(accountingChart.isQuantity());
                if (accountingChart.getAccChartAuxiliaries() != null) {
                    if(accountingChart.getAccChartAuxiliaries().size() != 0){
                        //运营科目辅助核算
                        List<AccountingOperatingChartAuxiliary> accAuxs = accOpChart.getAccOperatingChartAuxiliaryList();
                        for (int i = 0; i < accountingChart.getAccChartAuxiliaries().size(); i++) {
                            //会计科目辅助核算
                            AccountingChartAuxiliary accAux = accountingChart.getAccChartAuxiliaries().get(i);
                            //运营科目辅助核算
                            if(accAuxs.size() <= i){
                                AccountingOperatingChartAuxiliary accOpChartAuxiliary = new AccountingOperatingChartAuxiliary();
                                accOpChartAuxiliary.setId(SpringManager.getBean(SequenceService.class).getId(AccountingOperatingChartAuxiliary.CONST_TABLE_NAME));
                                accOpChartAuxiliary.setSequence(accAux.getSequence());
                                accOpChartAuxiliary.setAccAuxiliaryProject(accAux.getAccAuxiliaryProject());
                                accOpChartAuxiliary.setAccOperatingChart(accOpChart);
                                accAuxs.add(accOpChartAuxiliary);
                            }else {
                                AccountingOperatingChartAuxiliary accOpChartAuxiliary = accAuxs.get(i);
                                accOpChartAuxiliary.setSequence(accAux.getSequence());
                                accOpChartAuxiliary.setAccAuxiliaryProject(accAux.getAccAuxiliaryProject());
                            }
                        }
                    } else {
                        accOpChart.getAccOperatingChartAuxiliaryList().clear();
                    }
                }
                accountingOperatingChartRepository.save(accOpChart);//保存转化后的运营科目表,此时运营科目表已有数据
            });
        }
    }

    /**
     * 树形查找集团科目表
     *
     * @param request
     * @return
     */
    public List<Map<String, String>> findAllAccChart(SimpleRequest request) {

        Map fieldMap = new HashMap();
        String accSystem = null;
        try {
            accSystem = request.get("accSystem");
            fieldMap.put("accSystem", accSystem);
        } catch (Exception e) {

        }
        List<Map> fields = request.get("condition");
        if (fields.isEmpty() && accSystem == null) throw new RuntimeException("请输入科目");
        fields.stream().forEach(field -> {
            if (field.get("field").toString().equals("accSystem")) {
                fieldMap.put("accSystem", field.get("value").toString());
            }
            if (field.get("field").toString().equals("accGroup")) {
                fieldMap.put("accGroup", field.get("value").toString());
            }
        });
        if (fieldMap.containsKey("accSystem") == false) throw new RuntimeException("会计科目表必填选项，请选择！");
        accSystem = fieldMap.get("accSystem").toString();
        String accGroup = null;
        if (fieldMap.containsKey("accGroup")) {
            accGroup = fieldMap.get("accGroup").toString();
        }
        List<Map<String, String>> accountingCharts;
        if (accGroup == null || accGroup == "") {
            accountingCharts = accountingChartRepository.findByAccSystem_Id(accSystem);
        } else {
            accountingCharts = accountingChartRepository.findByAccGroup_IdAndAccSystem_Id(accGroup, accSystem);
        }
        if (accountingCharts.size() != 0 || !accountingCharts.isEmpty()) {
            String rule = accountingSystemRepository.findOne(accSystem).getAccIdRule();
            accountingCharts.stream().forEach(accountingChart -> {
                accountingChart.put("path", getPath(rule, accountingChart.get("code").toString()));
            });
        }
        return accountingCharts;
    }

    private String getPath(String rule, String code) {
        List l = Arrays.asList(rule.split("/"));
        int iLen = 0;
        String path = "";
        int iKMID = code.length();
        for (int i = 0; i < l.size(); i++) {
            int j = Integer.parseInt(l.get(i).toString());
            if (iLen + j > iKMID) {
                break;
            }
            String pathCODE = code.substring(iLen, iLen + j);
            path = path != "" ? path + "/" + pathCODE : pathCODE;
            iLen = iLen + j;
        }
        return path;
    }
}
